package com.wande.dataplatform.filecollection.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wande.common.core.exception.ServiceException;
import com.wande.common.mybatis.core.page.PageQuery;
import com.wande.common.mybatis.core.page.TableDataInfo;
import com.wande.dataplatform.filecollection.common.enums.FileCollectionErrorCode;
import com.wande.dataplatform.filecollection.domain.MappingRule;
import com.wande.dataplatform.filecollection.domain.bo.MappingRuleBo;
import com.wande.dataplatform.filecollection.domain.dto.FieldInfo;
import com.wande.dataplatform.filecollection.domain.dto.FieldMapping;
import com.wande.dataplatform.filecollection.domain.dto.ValidationResult;
import com.wande.dataplatform.filecollection.domain.vo.MappingRuleVo;
import com.wande.dataplatform.filecollection.mapper.MappingRuleMapper;
import com.wande.dataplatform.filecollection.mapper.MappingRuleVoMapper;
import com.wande.dataplatform.filecollection.parser.IFileParser;
import com.wande.dataplatform.filecollection.parser.ParserConfig;
import com.wande.dataplatform.filecollection.service.IFileMappingService;
import com.wande.dataplatform.filecollection.service.IFileParsingService;
import com.wande.dataplatform.filecollection.transform.ITransformFunction;
import com.wande.dataplatform.filecollection.transform.TransformFunctionRegistry;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件映射服务实现
 *
 * @author wande
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileMappingServiceImpl implements IFileMappingService {

    private final MappingRuleMapper mappingRuleMapper;
    private final MappingRuleVoMapper mappingRuleVoMapper;
    private final IFileParsingService fileParsingService;
    private final TransformFunctionRegistry transformFunctionRegistry;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createMappingRule(MappingRuleBo bo) {
        // 检查规则编码是否重复
        LambdaQueryWrapper<MappingRule> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(MappingRule::getRuleCode, bo.getRuleCode());
        if (mappingRuleMapper.selectCount(wrapper) > 0) {
            throw new ServiceException(FileCollectionErrorCode.RULE_CODE_DUPLICATE.getMessage());
        }

        // 转换为实体
        MappingRule mappingRule = BeanUtil.toBean(bo, MappingRule.class);
        
        // 序列化字段映射和校验规则
        if (CollUtil.isNotEmpty(bo.getFieldMappings())) {
            mappingRule.setFieldMappings(JSONUtil.toJsonStr(bo.getFieldMappings()));
        }
        if (CollUtil.isNotEmpty(bo.getValidationRules())) {
            mappingRule.setValidationRules(JSONUtil.toJsonStr(bo.getValidationRules()));
        }

        mappingRuleMapper.insert(mappingRule);
        return mappingRule.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMappingRule(MappingRuleBo bo) {
        MappingRule mappingRule = mappingRuleMapper.selectById(bo.getId());
        if (mappingRule == null) {
            throw new ServiceException(FileCollectionErrorCode.MAPPING_RULE_NOT_FOUND.getMessage());
        }

        // 检查规则编码是否重复
        if (!mappingRule.getRuleCode().equals(bo.getRuleCode())) {
            LambdaQueryWrapper<MappingRule> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(MappingRule::getRuleCode, bo.getRuleCode());
            wrapper.ne(MappingRule::getId, bo.getId());
            if (mappingRuleMapper.selectCount(wrapper) > 0) {
                throw new ServiceException(FileCollectionErrorCode.RULE_CODE_DUPLICATE.getMessage());
            }
        }

        // 更新实体
        BeanUtil.copyProperties(bo, mappingRule);
        
        // 序列化字段映射和校验规则
        if (CollUtil.isNotEmpty(bo.getFieldMappings())) {
            mappingRule.setFieldMappings(JSONUtil.toJsonStr(bo.getFieldMappings()));
        }
        if (CollUtil.isNotEmpty(bo.getValidationRules())) {
            mappingRule.setValidationRules(JSONUtil.toJsonStr(bo.getValidationRules()));
        }

        mappingRuleMapper.updateById(mappingRule);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMappingRule(Long id) {
        MappingRule mappingRule = mappingRuleMapper.selectById(id);
        if (mappingRule == null) {
            throw new ServiceException(FileCollectionErrorCode.MAPPING_RULE_NOT_FOUND.getMessage());
        }

        mappingRuleMapper.deleteById(id);
    }

    @Override
    public MappingRuleVo getMappingRule(Long id) {
        MappingRule mappingRule = mappingRuleMapper.selectById(id);
        if (mappingRule == null) {
            throw new ServiceException(FileCollectionErrorCode.MAPPING_RULE_NOT_FOUND.getMessage());
        }

        return convertToVo(mappingRule);
    }

    @Override
    public TableDataInfo<MappingRuleVo> listMappingRules(MappingRuleBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<MappingRule> wrapper = buildQueryWrapper(bo);
        Page<MappingRule> page = mappingRuleMapper.selectPage(pageQuery.build(), wrapper);
        
        // 使用映射器转换为 VO
        List<MappingRuleVo> voList = page.getRecords().stream()
                .map(mappingRuleVoMapper::toVo)
                .collect(java.util.stream.Collectors.toList());
        
        Page<MappingRuleVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(voList);
        
        return TableDataInfo.build(voPage);
    }

    @Override
    public List<FieldInfo> detectFileFields(MultipartFile file, String fileType) {
        try {
            IFileParser parser = fileParsingService.getParser(fileType);
            if (parser == null) {
                throw new ServiceException(FileCollectionErrorCode.UNSUPPORTED_FILE_TYPE.getMessage());
            }

            ParserConfig config = new ParserConfig();
            return parser.detectFields(file.getInputStream(), config);
        } catch (Exception e) {
            log.error("检测文件字段失败", e);
            throw new ServiceException(FileCollectionErrorCode.FILE_PARSE_ERROR.getMessage());
        }
    }

    @Override
    public List<String> listTargetTables(String database) {
        // TODO: 实现从Doris查询表列表
        // 这里需要集成Doris连接管理器
        List<String> tables = new ArrayList<>();
        return tables;
    }

    @Override
    public List<FieldInfo> getTableFields(String database, String table) {
        // TODO: 实现从Doris查询表字段
        // 这里需要集成Doris连接管理器
        List<FieldInfo> fields = new ArrayList<>();
        return fields;
    }

    @Override
    public ValidationResult validateMapping(MappingRuleBo bo) {
        ValidationResult result = new ValidationResult();

        // 验证字段映射
        if (CollUtil.isEmpty(bo.getFieldMappings())) {
            result.addError(ValidationResult.ValidationError.builder()
                .fieldName("fieldMappings")
                .errorMessage("字段映射不能为空")
                .build());
            return result;
        }

        // 验证每个字段映射
        for (FieldMapping mapping : bo.getFieldMappings()) {
            if (StrUtil.isBlank(mapping.getSourceField())) {
                result.addError(ValidationResult.ValidationError.builder()
                    .fieldName("sourceField")
                    .errorMessage("源字段名不能为空")
                    .build());
            }
            if (StrUtil.isBlank(mapping.getTargetField())) {
                result.addError(ValidationResult.ValidationError.builder()
                    .fieldName("targetField")
                    .errorMessage("目标字段名不能为空")
                    .build());
            }
            
            // 验证转换函数
            if (StrUtil.isNotBlank(mapping.getTransformFunction())) {
                ITransformFunction function = transformFunctionRegistry.getFunction(mapping.getTransformFunction());
                if (function == null) {
                    result.addError(ValidationResult.ValidationError.builder()
                        .fieldName("transformFunction")
                        .errorMessage("转换函数不存在: " + mapping.getTransformFunction())
                        .build());
                }
            }
        }

        return result;
    }

    @Override
    public Map<String, Object> transformData(Map<String, Object> sourceData, Long mappingRuleId) {
        MappingRule mappingRule = mappingRuleMapper.selectById(mappingRuleId);
        if (mappingRule == null) {
            throw new ServiceException(FileCollectionErrorCode.MAPPING_RULE_NOT_FOUND.getMessage());
        }

        Map<String, Object> targetData = new HashMap<>();
        
        // 解析字段映射
        List<FieldMapping> fieldMappings = JSONUtil.toList(mappingRule.getFieldMappings(), FieldMapping.class);
        
        for (FieldMapping mapping : fieldMappings) {
            Object sourceValue = sourceData.get(mapping.getSourceField());
            Object targetValue = sourceValue;

            // 应用转换函数
            if (StrUtil.isNotBlank(mapping.getTransformFunction()) && sourceValue != null) {
                ITransformFunction function = transformFunctionRegistry.getFunction(mapping.getTransformFunction());
                if (function != null) {
                    targetValue = function.transform(sourceValue, mapping.getTransformParams());
                }
            }

            // 处理空值
            if (targetValue == null && StrUtil.isNotBlank(mapping.getDefaultValue())) {
                targetValue = mapping.getDefaultValue();
            }

            targetData.put(mapping.getTargetField(), targetValue);
        }

        return targetData;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<MappingRule> buildQueryWrapper(MappingRuleBo bo) {
        LambdaQueryWrapper<MappingRule> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StrUtil.isNotBlank(bo.getRuleName()), MappingRule::getRuleName, bo.getRuleName());
        wrapper.eq(StrUtil.isNotBlank(bo.getRuleCode()), MappingRule::getRuleCode, bo.getRuleCode());
        wrapper.eq(StrUtil.isNotBlank(bo.getFileType()), MappingRule::getFileType, bo.getFileType());
        wrapper.orderByDesc(MappingRule::getCreateTime);
        return wrapper;
    }

    /**
     * 转换为VO
     */
    private MappingRuleVo convertToVo(MappingRule mappingRule) {
        return mappingRuleVoMapper.toVo(mappingRule);
    }

    @Override
    public ValidationResult testValidationRules(MappingRuleBo bo) {
        // 创建测试数据
        Map<String, Object> testData = new HashMap<>();
        testData.put("test_field", "test_value");
        testData.put("number_field", 100);
        testData.put("date_field", "2024-01-01");
        
        // 创建临时映射规则
        MappingRule tempRule = new MappingRule();
        tempRule.setValidationRules(JSONUtil.toJsonStr(bo.getValidationRules()));
        
        // 使用ValidationService进行校验
        com.wande.dataplatform.filecollection.validation.ValidationService validationService = 
            new com.wande.dataplatform.filecollection.validation.ValidationService(
                new com.wande.dataplatform.filecollection.validation.ValidationRuleRegistry()
            );
        
        return validationService.validateRecord(testData, tempRule);
    }

    @Override
    public List<String> getAvailableValidationTypes() {
        List<String> types = new ArrayList<>();
        types.add("NOT_NULL");
        types.add("FORMAT");
        types.add("RANGE");
        types.add("ENUM");
        types.add("UNIQUE");
        return types;
    }
}
